package com.sndscl.rpc.call;

import com.sndscl.rpc.common.constant.SndSclConstant;
import com.sndscl.rpc.common.dto.RpcRequest;
import com.sndscl.rpc.common.dto.RpcResponse;
import com.sndscl.rpc.spring.ApplicationContextUtils;
import com.sndscl.rpc.zk.ZkUtil;
import org.springframework.core.env.Environment;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.SynchronousQueue;

/**
 * @Description
 * @Author lsh
 * @Date 2020/10/23 17:01
 **/
public class SndSclCall {
    //记录每个接口的服务器列表
    private static Map<String, HashSet<String>> interfaceListtMap = new ConcurrentHashMap<>();
    private static Map<String,NettyClient> nettyClientMap = new ConcurrentHashMap<>();
    private static Map<String,NettyClient> timeOutNettyClientMap =  new ConcurrentHashMap();
    static Map<String, SynchronousQueue<RpcResponse>> synchronousQueueMap = new ConcurrentHashMap<>();

    public static void init(){
        Environment environment = ApplicationContextUtils.getEnvironment();
        String zkurl = environment.getProperty(SndSclConstant.SPRING_PRO_ZK__NAME);
        if(zkurl == null && "".equals("")){
            System.err.println("SndScl RPC INIT ERROR,PROPERTY "+zkurl+"  isEmpty！");
            return;
        }
        ZkUtil.connection(zkurl);
        Map<String, HashSet<String>> serversMap =  ZkUtil.addWatcher();
        if(serversMap != null ){
            getServerInterface(serversMap);
        }
    }

    public synchronized static void getServerInterface(Map<String, HashSet<String>> serversMap){
        interfaceListtMap = convertServerInterface(serversMap);
        initNettyClients(serversMap);
    }

    private synchronized static void  initNettyClients(Map<String, HashSet<String>> serversMap){
        if(serversMap != null ){
            Set<String> servers = serversMap.keySet();
            for(String server: servers){
                //创建客户端连接
                if(!nettyClientMap.containsKey(server)){
                    String[] serverInfo = server.split(":");
                    String hostIp = serverInfo[0];
                    String port = serverInfo[1];
                    NettyClient nettyClient = new NettyClient(hostIp,Integer.valueOf(port),server);
                    nettyClient.doConnection();
                }
            }
        }
    }

    private static Map<String,HashSet<String>> convertServerInterface(Map<String, HashSet<String>> serverListtMap){
        //记录每个接口的服务器列表
        Map<String, HashSet<String>> interfaceListtMap = new HashMap<>();
        serverListtMap.forEach((k,v)->{
            v.forEach((interfaceSign)->{
                HashSet<String> interfaceSignServers = interfaceListtMap.get(interfaceSign);
                if(interfaceSignServers == null){
                    interfaceSignServers = new HashSet<>();
                    interfaceSignServers.add(k);
                    interfaceListtMap.put(interfaceSign,interfaceSignServers);
                }else{
                    interfaceSignServers.add(k);
                }
            });
        });
        return interfaceListtMap;
    }


    private static NettyClient choose(Set<String> servers){
        //随机选取
        String[] serverArrays = new String[servers.size()];
        serverArrays = servers.toArray(serverArrays);
        String serverIp = serverArrays[new Random().nextInt(serverArrays.length)];
        return nettyClientMap.get(serverIp);
    }

    static NettyClient rpcCall(RpcRequest rpcRequest){
        //获得接口的服务器列表
        Set<String> servers = interfaceListtMap.get(rpcRequest.getMethodSign());
        NettyClient nettyClient = choose(servers);
        if(nettyClient != null){
            //TODO 判断连接是否可用
            if(nettyClient.channelIsActive()){
                nettyClient.send(rpcRequest);
            }
        }else{
            //TODO 未获取到客户端连接
        }
        return nettyClient;
    }

    static NettyClient rpcCall(RpcRequestWarp rpcRequestWarp){
        RpcRequest rpcRequest = rpcRequestWarp.getRpcRequest();
        List<NettyClient> failClients = rpcRequestWarp.getFailClients();
        System.out.println(interfaceListtMap);
        System.out.println(rpcRequest.getMethodSign());
        Set<String> servers = interfaceListtMap.get(rpcRequest.getMethodSign());
        if(servers == null){
            System.err.println("NOT FOUND REMOTE SERVER！");
            return null;
        }
        Set<String> serversCopy = new HashSet<>();
        serversCopy.addAll(servers);
        //过滤掉失败的服务器
        for(NettyClient failClient : failClients){
            serversCopy.remove(failClient.getKey());
        }
        NettyClient nettyClient = choose(serversCopy);
        if(nettyClient != null){
            //TODO 判断连接是否可用
            if(nettyClient.channelIsActive()){
                nettyClient.send(rpcRequest);
            }
        }else{
            //TODO 未获取到客户端连接
        }
        return nettyClient;
    }

    public static void registerClient(String key,NettyClient client){
        nettyClientMap.put(key,client);
        //判断 是第一次连接还是中断后重连
        // 中断后重连，从重连列表中移除
        if(timeOutNettyClientMap.containsKey(key)){
            timeOutNettyClientMap.remove(key);
        }
    }

    public static NettyClient removeClient(String key){
        return nettyClientMap.remove(key);
    }

    public static void removemoveToReConnectionMap(String key){
        if(timeOutNettyClientMap.containsKey(key)){
            timeOutNettyClientMap.remove(key);
        }
    }

    //移动到重连列表，避免获取到正在重连的客户端连接
    public static void moveToReConnectionMap(String key){
        NettyClient nettyClient = removeClient(key);
        if(nettyClient != null){
            timeOutNettyClientMap.put(key,nettyClient);
        }
    }
}
